package entidades;

import java.util.logging.Level;
import java.util.logging.Logger;
import util.*;
import java.util.Map;
import java.util.Date;
import java.util.List;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.google.gson.Gson;
import entidades.excepciones.RepeatedWOException;
import java.util.*;
import migracion.ArregloPorLoDeSeba;

/**
 * @author JFM
 */
public class OrdenTrabajo extends Entidad
	{
	private String identificador;
	private int ordenVentaId;
	private int formatoId;
	private int estadoId;
	private long cantidad;
	private long metros;
	private Date fechaPrometida;

	private int cicloNewlongId;
	private int cicloNewlongTurno;
	private Date cicloNewlongInicio;
	private Date cicloNewlongFin;
	
	private int cicloUtecoId;
	private int cicloUtecoTurno;
	private Date cicloUtecoInicio;
	private Date cicloUtecoFin;

	private OrdenVenta ordenVenta;
	private Formato formato;
	private EstadoTrabajo estado;
	private CicloNewlong cicloNewlong;
	private CicloUteco cicloUteco;
        private int utecoDefault;
        
        private boolean recalculable;

    public boolean isRecalculable() {
        return recalculable;
    }

    public void setRecalculable(boolean recalculable) {
        this.recalculable = recalculable;
    }
        
	
	static final String NOMBRE_TABLA = "ordenes_trabajo";

	public static final int SIN_IMPRESION = 1;
	public static final int IMPRESION_PENDIENTE = 2;
	public static final int IMPRESION_PLANIFICADA = 3;
	public static final int IMPRESION_TERMINADA = 4;
	public static final int SIN_CONFECCION = 5;
	public static final int CONFECCION_PENDIENTE = 6;
	public static final int CONFECCION_PLANIFICADA = 7;
	public static final int CONFECCION_TERMINADA = 8;
	private boolean soloImpresion;
	// --- Constructores --- //

	public OrdenTrabajo()
		{
		identificador = "";
		ordenVentaId = 0;
		formatoId = 0;
		estadoId = 0;	
		cantidad = 0;
		metros = 0;
		fechaPrometida = null;

		cicloNewlongId = 0;
		cicloNewlongTurno = 0;
		cicloNewlongInicio = null;
		cicloNewlongFin = null;
                soloImpresion = false;
		cicloUtecoId = 0;
		cicloUtecoTurno = 0;
                utecoDefault = 0;
		cicloUtecoInicio = null;
		cicloUtecoFin = null;	
		ordenVenta = null;
		formato = null;
		estado = null;
		cicloNewlong = null;
		cicloUteco = null;
		}

	public OrdenTrabajo(int id) throws SQLException
		{ super(id); }

	public OrdenTrabajo(String id) throws SQLException
		{ super(id); }

	public OrdenTrabajo(ResultSet result) throws SQLException
		{ super(result); }

        @Override
        public void borrar() throws SQLException{
            super.borrar();
            
            /*Recalcular Acarreo*/
             ControlDeCiclosNewlong control = new ControlDeCiclosNewlong();
             control.recalcularAcarreoDeCiclos();
        }


	// --- Metodos get()/set() --- //

	public String getIdentificador()
		{ return identificador; }
	public void setIdentificador(String identificador){
            this.identificador = (identificador != null)? identificador : "";            
        }

        public static void checkIdentificador(String identif) throws RepeatedWOException{
             try {
                long res = 0;
                ResultSet result = MySQL.executeQuery(
                    "select count(*) cant from ordenes_trabajo where identificador = '"+identif+"'"
                    );
                if(result.next()) {res = result.getLong("cant");}
                result.getStatement().close();
                
                if(res>0){
                    throw new RepeatedWOException(identif);
                }
            } catch (SQLException e) {
            }
        }
        
        public static long ocurrenciasIdentificadorWO(String identif){
             long res = 0;
             try {
                ResultSet result = MySQL.executeQuery(
                    "select count(*) cant from ordenes_trabajo where identificador = '"+identif+"'"
                    );
                if(result.next()) {res = result.getLong("cant");}
                result.getStatement().close();

            } catch (SQLException e) {}
            return res;
        }
        
	public long getCantidad()
		{ return cantidad; }
	public void setCantidad(long cantidad)
		{ this.cantidad = cantidad; }
	public void setCantidad(String cantidad)
		{ try{ this.cantidad = Long.parseLong(cantidad); }catch(Exception e) {} }

	public long getMetros()
		{ return metros; }
	public void setMetros(long metros)
		{ this.metros = metros; }
	public void setMetros(String metros)
		{ try{ this.metros = Long.parseLong(metros); }catch(Exception e) {} }

	public void setFechaPrometida(Date fechaPrometida)
		{ this.fechaPrometida = fechaPrometida; }
	public void setFechaPrometida(String fechaPrometida)
		{ this.fechaPrometida = Util.parseDate(fechaPrometida); }
	public Date getFechaPrometida() throws SQLException
		{ return fechaPrometida; }
	public String getFechaPrometidaToString() throws SQLException
		{ return Util.format(fechaPrometida, "dd/MM/yyyy"); }

	public int getOrdenVentaId()
		{ return ordenVentaId; }
	public void setOrdenVentaId(int ordenVentaId)
		{ this.ordenVentaId = ordenVentaId; }
	public void setOrdenVentaId(String ordenVentaId)
		{ try{ this.ordenVentaId = Integer.parseInt(ordenVentaId); }catch(Exception e) {} }

	public OrdenVenta getOrdenVenta() throws SQLException
		{
		if(ordenVenta == null || ordenVentaId != ordenVenta.getId())
			{ ordenVenta = new OrdenVenta(ordenVentaId); }
		return ordenVenta;
		}
	public void setOrdenVenta(OrdenVenta ordenVenta)
		{ this.ordenVenta = ordenVenta; }
	
	public int getFormatoId()
		{ return formatoId; }
	public void setFormatoId(int formatoId)
		{ this.formatoId = formatoId; }
	public void setFormatoId(String formatoId)
		{ try{ this.formatoId = Integer.parseInt(formatoId); }catch(Exception e) {} }

	public void setFormato(Formato formato)
		{ this.formato = formato; }
	public Formato getFormato() throws SQLException
		{
		if(formato == null || formatoId != formato.getId())
			{ formato = new Formato(formatoId); }
		return formato;
		}

	public int getEstadoId()
		{ return estadoId; }
	public void setEstadoId(int estadoId)
		{ this.estadoId = estadoId; }
	public void setEstadoId(String estadoId)
		{ try{ this.estadoId = Integer.parseInt(estadoId); }catch(Exception e) {} }

	public void setEstado(EstadoTrabajo estado)
		{ this.estado = estado; }
	public EstadoTrabajo getEstado() throws SQLException
		{
		if(estado == null || estadoId != estado.getId())
			{ estado = new EstadoTrabajo(estadoId); }
		return estado;
		}

         public boolean isSoloImpresion()
		{ return soloImpresion; }
	public void setSoloImpresion(boolean soloImpresion)
		{ this.soloImpresion = soloImpresion; }
        public void setSoloImpresion(String soloImpresion)
		{
                  this.soloImpresion = soloImpresion != null && ( soloImpresion.compareTo("1") == 0 || soloImpresion.compareTo("true") == 0);
                }

	
	public int getEstadoImpresion()
		{
		if(estadoId == EstadoTrabajo.IMPRESO || (estadoId == EstadoTrabajo.CONFECCIONADO && cicloUtecoId > 0))
			{ return IMPRESION_TERMINADA; }
		else
			{
			if(cicloUtecoId == 0)
				{ return SIN_IMPRESION; }
			else
				{
				try{
					CicloUteco cu = getCicloUteco();
					if(cu != null && cu.isPlanificado())
						{ return IMPRESION_PLANIFICADA; }
					}catch(Exception e) {}
				return IMPRESION_PENDIENTE;
				}
			}
		}
	public int getEstadoConfeccion()
		{
		if(estadoId == EstadoTrabajo.CONFECCIONADO)
			{ return CONFECCION_TERMINADA; }
		else
			{
			if(cicloNewlongId == 0)
				{ return SIN_CONFECCION; }
			else
				{
				try{
					CicloNewlong cn = getCicloNewlong();
					if(cn != null && cn.isPlanificado())
						{ return CONFECCION_PLANIFICADA; }
					}catch(Exception e) {}
				return CONFECCION_PENDIENTE;
				}
			}
		}
	public boolean validarEstados()
		{
		int impresion = getEstadoImpresion();
		int confeccion = getEstadoConfeccion();
		if(impresion != SIN_IMPRESION && confeccion != SIN_CONFECCION)
			{
			if(confeccion >= CONFECCION_PLANIFICADA && impresion == IMPRESION_PENDIENTE) return false;
			if(confeccion == CONFECCION_TERMINADA && impresion != IMPRESION_TERMINADA) return false;
			if (getCicloNewlongInicio() != null){
                            return getCicloUtecoFin().getTime() <= getCicloNewlongInicio().getTime();
                            }
			}
		return true;
		}
	
	
	public int getCicloNewlongId()
		{ return cicloNewlongId; }
	public void setCicloNewlongId(int cicloNewlongId)
		{ this.cicloNewlongId = cicloNewlongId; }
	public void setCicloNewlongId(String cicloNewlongId)
		{ try{ this.cicloNewlongId = Integer.parseInt(cicloNewlongId); }catch(Exception e) {} }

	public CicloNewlong getCicloNewlong() throws SQLException
		{
		if(cicloNewlongId > 0)
			{
			if(cicloNewlong == null || cicloNewlongId != cicloNewlong.getId())
				{ cicloNewlong = new CicloNewlong(cicloNewlongId); }
			return cicloNewlong;
			}
		return null;
		}
	public void setCicloNewlong(CicloNewlong ciclo)
		{ if(ciclo == null || cicloNewlongId == ciclo.getId()) cicloNewlong = ciclo; }
	
	public int getCicloNewlongTurno()
		{ return cicloNewlongTurno; }
	public void setCicloNewlongTurno(int cicloNewlongTurno)
		{ this.cicloNewlongTurno = cicloNewlongTurno; }
	public void setCicloNewlongTurno(String cicloNewlongTurno)
		{ try{ this.cicloNewlongTurno = Integer.parseInt(cicloNewlongTurno); }catch(Exception e) {} }	

	public Date getCicloNewlongInicio()
		{ return cicloNewlongInicio; }
	public void setCicloNewlongInicio(Date cicloNewlongInicio)
		{ this.cicloNewlongInicio = cicloNewlongInicio; }
	public void setCicloNewlongInicio(String cicloNewlongInicio)
		{ this.cicloNewlongInicio = Util.parseDate(cicloNewlongInicio); }
	public String getCicloNewlongInicioToString()
		{ return Util.format(cicloNewlongInicio, "dd/MM/yyyy"); }

	public Date getCicloNewlongFin()
		{ return cicloNewlongFin; }
	public void setCicloNewlongFin(Date cicloNewlongFin)
		{ this.cicloNewlongFin = cicloNewlongFin; }
	public void setCicloNewlongFin(String cicloNewlongFin)
		{ this.cicloNewlongFin = Util.parseDatetime(cicloNewlongFin); }
	public String getCicloNewlongFinToString()
		{ return Util.format(cicloNewlongFin, "dd/MM/yyyy"); }
	
	public int getCicloUtecoId()
		{ return cicloUtecoId; }
	public void setCicloUtecoId(int cicloUtecoId)
		{ this.cicloUtecoId = cicloUtecoId; }
        public int getUtecoDefault()
		{ return utecoDefault; }
	public void setUtecoDefault(int utecoDefault)
		{ this.utecoDefault = utecoDefault; }

	public void setCicloUtecoId(String cicloUtecoId)
		{ try{ this.cicloUtecoId = Integer.parseInt(cicloUtecoId); }catch(Exception e) {} }

	public CicloUteco getCicloUteco() throws SQLException
		{
		if(cicloUtecoId > 0)
			{
			if(cicloUteco == null || cicloUtecoId != cicloUteco.getId())
				{ cicloUteco = new CicloUteco(cicloUtecoId); }
			return cicloUteco;
			}
		return null;
		}
	public void setCicloUteco(CicloUteco ciclo)
		{ if(ciclo == null || cicloUtecoId == ciclo.getId()) cicloUteco = ciclo; }
	
	public int getCicloUtecoTurno()
		{ return cicloUtecoTurno; }
	public void setCicloUtecoTurno(int cicloUtecoTurno)
		{ this.cicloUtecoTurno = cicloUtecoTurno; }
	public void setCicloUtecoTurno(String cicloUtecoTurno)
		{ try{ this.cicloUtecoTurno = Integer.parseInt(cicloUtecoTurno); }catch(Exception e) {} }	

	public Date getCicloUtecoInicio()
		{ return cicloUtecoInicio; }
	public void setCicloUtecoInicio(Date cicloUtecoInicio)
		{ this.cicloUtecoInicio = cicloUtecoInicio; }
	public void setCicloUtecoInicio(String cicloUtecoInicio)
		{ this.cicloUtecoInicio = Util.parseDate(cicloUtecoInicio); }
	public String getCicloUtecoInicioToString()
		{ return Util.format(cicloUtecoInicio, "dd/MM/yyyy"); }

	public Date getCicloUtecoFin()
		{ return cicloUtecoFin; }
	public void setCicloUtecoFin(Date cicloUtecoFin)
		{ this.cicloUtecoFin = cicloUtecoFin; }
	public void setCicloUtecoFin(String cicloUtecoFin)
		{ this.cicloUtecoFin = Util.parseDatetime(cicloUtecoFin); }
	public String getCicloUtecoFinToString()
		{ return Util.format(cicloUtecoFin, "dd/MM/yyyy"); }

	@Override
	public String getDescriptor()
		{ return identificador; }

	@Override
	public String toJson()
		{
		HashMap map = new HashMap();
		map.put("id", id);
		map.put("identificador", identificador);
		map.put("orden_venta_id", ordenVentaId);
		map.put("formato_id", formatoId);
		map.put("estado_id", estadoId);
                map.put("soloImpresion", soloImpresion);
		map.put("cantidad", cantidad);
		map.put("metros", cantidad);
		map.put("fecha_prometida", Util.format(fechaPrometida, "dd/MM/yyyy"));

		map.put("ciclo_newlong_id", cicloNewlongId);
		map.put("ciclo_newlong_turno", cicloNewlongTurno);
		map.put("ciclo_newlong_inicio", (cicloNewlongInicio!=null)? Util.format(cicloNewlongInicio, "dd/MM/yyyy HH:mm:ss") : "");
		map.put("ciclo_newlong_fin", (cicloNewlongFin!=null)? Util.format(cicloNewlongFin, "dd/MM/yyyy HH:mm:ss") : "");

		map.put("ciclo_uteco_id", cicloUtecoId);
                map.put("uteco_default", utecoDefault);
		map.put("ciclo_uteco_turno", cicloUtecoTurno);
		map.put("ciclo_uteco_inicio", (cicloUtecoInicio!=null)? Util.format(cicloUtecoInicio, "dd/MM/yyyy HH:mm:ss") : "");
		map.put("ciclo_uteco_fin", (cicloUtecoFin!=null)? Util.format(cicloUtecoFin, "dd/MM/yyyy HH:mm:ss") : "");
		
		try{
			map.put("formato", getFormato().getDescriptor());
			map.put("linea", getFormato().getLinea().getDescripcion());
			map.put("estado", getEstado().getDescripcion());
			map.put("orden_venta_identificador", getOrdenVenta().getIdentificador());
			
			CicloNewlong cn = getCicloNewlong();
			CicloUteco cu = getCicloUteco();
			map.put("newlong", (cn!=null)? cn.getNewlong().getDescripcion() : "" );
			map.put("uteco", (cn!=null)? cu.getUteco().getDescripcion() : "" );
			}catch(SQLException e) {}

		return new Gson().toJson(map);
		}



	// --- Metodos MySQL --- //

	@Override
	public String getNombreTabla()
		{ return NOMBRE_TABLA; }

	@Override
	public void leer(ResultSet result, String prefijo) throws SQLException
		{
		setId(result.getInt(prefijo + "id"));
		setOrdenVentaId(result.getString(prefijo + "orden_venta_id"));
		setIdentificador(result.getString(prefijo + "identificador"));
		setFormatoId(result.getInt(prefijo + "formato_id"));
		setEstadoId(result.getInt(prefijo + "estado_id"));
                setSoloImpresion(result.getBoolean(prefijo + "solo_impresion"));
		setCantidad(result.getLong(prefijo + "cantidad"));
		setMetros(result.getLong(prefijo + "metros"));
		setFechaPrometida(result.getDate(prefijo + "fecha_prometida"));

		setCicloNewlongId(result.getInt(prefijo + "ciclo_newlong_id"));
		setCicloNewlongTurno(result.getInt(prefijo + "ciclo_newlong_turno"));
		setCicloNewlongInicio(result.getDate(prefijo + "ciclo_newlong_inicio"));
		setCicloNewlongFin(result.getDate(prefijo + "ciclo_newlong_fin"));

		setCicloUtecoId(result.getInt(prefijo + "ciclo_uteco_id"));
		setCicloUtecoTurno(result.getInt(prefijo + "ciclo_uteco_turno"));
		setCicloUtecoInicio(result.getDate(prefijo + "ciclo_uteco_inicio"));
		setCicloUtecoFin(result.getDate(prefijo + "ciclo_uteco_fin"));
                setUtecoDefault(result.getInt(prefijo + "uteco_default"));
		}

	@Override
	public void guardar() throws SQLException
		{
               String idCicloUteco = null;
               if (cicloUtecoId > 0){
                   idCicloUteco = MySQL.format(cicloUtecoId);
               }
               ResultSet result = MySQL.executeQuery("Call OrdenesTrabajo_Save(" +
				MySQL.formatId(id) + "," +
				MySQL.format(identificador) + "," +
				MySQL.formatId(ordenVentaId) + "," +
				MySQL.formatId(formatoId) + "," +
				MySQL.formatId(estadoId) + "," +
				MySQL.format(cantidad) + "," +
				MySQL.format(metros) + "," +
				MySQL.formatDate(fechaPrometida) + "," +
				MySQL.formatId(cicloNewlongId) + "," +
				MySQL.format(cicloNewlongTurno) + "," +
				MySQL.format(cicloNewlongInicio) + "," +
				MySQL.format(cicloNewlongFin) + "," +
				idCicloUteco + "," +
				MySQL.format(cicloUtecoTurno) + "," +
				MySQL.format(cicloUtecoInicio) + "," +
                                MySQL.format(utecoDefault) + "," +
				MySQL.format(cicloUtecoFin) + "," +
                                MySQL.formatBit(soloImpresion) + ")");
		
		if(result.next())
			{
			if( result.getMetaData().getColumnCount() == 1)
				{
				String msj = result.getString("mensaje");
				throw new SQLException(msj);
				}
			else
				leer(result);
                         }

		result.getStatement().close();
                 
                //this.estadoId == EstadoTrabajo.PENDIENTE
                if (cicloNewlongId > 0 && (cicloUtecoId == 0 || this.recalculable)){
                    EtapaNewlong etapa = EtapaNewlong.buscar(cicloNewlongId, formatoId);
                    long disponible = etapa.getDisponible();
                    if (cantidad > etapa.getDisponible()){
                        etapa.setOcupado(etapa.getCantidad());
                        etapa.guardar();
                        long diferencia = cantidad - disponible;
                        long disponibleCiclo = this.getCicloNewlong().getDisponible();
                        List<EtapaNewlong> etapas = EtapaNewlong.listar(cicloNewlongId);
                        long totalEtapas = 0;
                        for (EtapaNewlong e : etapas){
                            if (e.getId() != etapa.getId() && diferencia > 0 ){
                                double proporcion = (double) e.getDisponible()/ disponibleCiclo;
                                long total = (long)(proporcion * diferencia  );
                                e.setOcupado(e.getOcupado() + total);
                                totalEtapas += total;
                                e.guardar();
                            }
                        }
                        
                        /*Sobrecargo el ciclo*/
                        if (totalEtapas < diferencia){
                            /*Distribuyo uniformemente lo que me falta para saldar la diferencia*/
                            long porcionUniforme = (diferencia - totalEtapas)/etapas.size();
                            long restoADistribuir = (diferencia - totalEtapas)%etapas.size();
                            
                            for (EtapaNewlong e : etapas){
                                e.setOcupado(e.getOcupado() + porcionUniforme);
                                e.guardar();
                            }
                            
                            /*Distribuyo el resto*/
                            EtapaNewlong primeraEtapa = etapas.get(0);
                            primeraEtapa.setOcupado(primeraEtapa.getOcupado() + restoADistribuir);
                            primeraEtapa.guardar();
                         }
                    }else{
                        etapa.setOcupado(etapa.getOcupado() + cantidad );
                        etapa.guardar();
                    }
                }
           

           if (cicloUtecoId == 0){
//               long dias = 0;
//               if (this.getOrdenVenta().getPais().getId() == Pais.ARGENTINA){
//                   dias = 86400000*7;
//               }else{
//                   dias = 86400000*14;
//               }

//             Date fechaInicio = new Date(this.getCicloNewlongInicio().getTime() - dias);
//               Date fechaInicioDeConfeccion = CicloNewlong.getFechaDeInicioDeConfeccion(
//                       this.getCicloNewlongId(),
//                       this.getFormatoId(),
//                       this.getCantidad()
//                       );
//               
               cicloUtecoId = CicloUteco.getCicloUtecoIdDisponibleByFecha(
                       cicloNewlongInicio,
                       this.getOrdenVenta().getPais().getId()
                      );
               
               /*Controla que se haya obtenido un ciclo uteco*/
               if( cicloUtecoId == 0 ){
                   String msj = "Elija una fecha posterior porque no existe fecha para asignar un ciclo uteco tan proximo.";
                   throw new SQLException(msj);
               }
               
               this.updateCicloUteco();
          }

      }

        public void updateCicloUteco() throws SQLException{
            if (cantidad < 50000){
                metros = (long) (metros + metros * 0.1);
            }else if (cantidad < 100000){
                metros = (long) (metros + metros * 0.06);
            }else{
                metros = (long) (metros + metros * 0.04);
            }
            ResultSet result = MySQL.executeQuery("Call OrdenesTrabajo_Save(" +
				MySQL.formatId(id) + "," +
				MySQL.format(identificador) + "," +
				MySQL.formatId(ordenVentaId) + "," +
				MySQL.formatId(formatoId) + "," +
				MySQL.formatId(estadoId) + "," +
				MySQL.format(cantidad) + "," +
				MySQL.format(metros) + "," +
				MySQL.formatDate(fechaPrometida) + "," +
				MySQL.formatId(cicloNewlongId) + "," +
				MySQL.format(cicloNewlongTurno) + "," +
				MySQL.format(cicloNewlongInicio) + "," +
				MySQL.format(cicloNewlongFin) + "," +
				MySQL.format(cicloUtecoId) + "," +
				MySQL.format(cicloUtecoTurno) + "," +
				MySQL.format(cicloUtecoInicio) + "," +
                                MySQL.format(utecoDefault) + "," +
				MySQL.format(cicloUtecoFin) + "," +
                                MySQL.formatBit(soloImpresion) + ")");


		if(result.next())
			{
			if( result.getMetaData().getColumnCount() == 1)
				{
				String msj = result.getString("mensaje");
				throw new SQLException(msj);
				}
			else
				leer(result);
                         }

		result.getStatement().close();
                
                //En caso de detectar anomalias con las etapas recalculo
                Integer cantidad = CicloNewlong.cantidadCiclosConProblemasDeCoincidencia();
                if(cantidad>0){
                    ArregloPorLoDeSeba.recalcularEtapasPorCiclos(this.cicloNewlongId);
                }
                
        }

                public void guardarCiclosNulos() throws SQLException
		{
		ResultSet result = MySQL.executeQuery("Call OrdenesTrabajo_Save(" +
				MySQL.formatId(id) + "," +
				MySQL.format(identificador) + "," +
				MySQL.formatId(ordenVentaId) + "," +
				MySQL.formatId(formatoId) + "," +
				MySQL.formatId(estadoId) + "," +
				MySQL.format(cantidad) + "," +
				MySQL.format(metros) + "," +
				MySQL.formatDate(fechaPrometida) + "," +
				null + "," +
				MySQL.format(cicloNewlongTurno) + "," +
				MySQL.format(cicloNewlongInicio) + "," +
				MySQL.format(cicloNewlongFin) + "," +
				null + "," +
				MySQL.format(cicloUtecoTurno) + "," +
				MySQL.format(cicloUtecoInicio) + "," +
                                MySQL.format(utecoDefault) + "," +
				MySQL.format(cicloUtecoFin) + "," +
                                MySQL.formatBit(soloImpresion) + ")");

		if(result.next())
			{
			if( result.getMetaData().getColumnCount() == 1)
				{
				String msj = result.getString("mensaje");
				throw new SQLException(msj);
				}
			else{
				sendMailAutorizacion();
                                leer(result);
                            }
			}

		result.getStatement().close();
		}

        private void sendMailAutorizacion() throws SQLException{
            
            String mensaje = "Cliente: " + this.getOrdenVenta().getLogotipo().getDescripcion() + "\n";
            mensaje += "\n";
            mensaje += "Fecha prometida: " + this.getFechaPrometidaToString() + "\n";
            mensaje += "\n";
            mensaje += "WO: " + this.getIdentificador() + "\n";
            mensaje += "\n";
            mensaje += "Fto: " + this.getFormato().getDescriptor() + "\n";
            mensaje += "\n";
            mensaje += this.getCantidad() + " bolsas " + "% (" + this.getOrdenVenta().getLinea().getDescripcion() + ")" + "\n";
            mensaje += "\n";
            mensaje += this.getOrdenVenta().getTipoPapel().getDescripcion() + "\n";
            mensaje += "\n";
            mensaje += "Manija: " + this.getOrdenVenta().getManija().getDescripcion();
            new MailSender("juliobardi@romipack.com.ar","Solicito autorización para vender antes de 30 días",mensaje,"zulmazorrilla@romipack.com.ar").start();
        }

	public static void cambiarCicloUteco(int id, Integer cicloId, Integer turno) throws SQLException
		{ if(id > 0) MySQL.executeUpdate("Call OrdenesTrabajo_CambiarCiclo('u', " + id + ", " + cicloId + ", " + turno + ", 0)"); }

	public static void cambiarCicloNewlong(int id, Integer cicloId, Integer turno, boolean recalcular) throws SQLException
		{ if(id > 0) MySQL.executeUpdate("Call OrdenesTrabajo_CambiarCiclo('n', " + id + ", " + cicloId + ", " + turno + ", "+MySQL.formatBit(recalcular)+")"); }

	public static void cambiarTurnoUteco(int id, int turno) throws SQLException
		{ cambiarCicloUteco(id, null, turno); }

	public static void cambiarTurnoNewlong(int id, int turno, boolean recalcular) throws SQLException
		{ cambiarCicloNewlong(id, null, turno, recalcular); }
		
	public static void borrar(String id) throws SQLException
		{ MySQL.executeUpdate("Call OrdenesTrabajo_Delete("+id+")"); }

	public static List<OrdenTrabajo> listar() throws SQLException
		{ return (List) Entidad.listar(OrdenTrabajo.class, NOMBRE_TABLA, "ciclo_newlong_inicio ASC"); }

	public static List<OrdenTrabajo> listar(String ids[]) throws SQLException
		{
		if(ids != null && ids.length > 0)
			{
			int c=0;
			String where = "";
			for(int i=0; i<ids.length; i++)
				{
				if(ids[i] != null && ids[i].length() != 0)
					{
					if(c!=0) where += " OR ";
					where += "id = " + ids[i];
					c++;
					}
				}
			if(where.length() == 0) where = "true";
			return (List) Entidad.buscar(OrdenTrabajo.class, NOMBRE_TABLA, where);
			}
		else
			{ return new LinkedList(); }
		}

	public static List<OrdenTrabajo> listarCicloUteco(int numero) throws Exception
		{ return OrdenTrabajoView.buscar("cu_numero = " + numero); }

        public static List<OrdenTrabajo> listarCicloUtecoByFecha(int numero) throws Exception
		{ return OrdenTrabajoView.buscar("cu_numero = " + numero); }

        public static List<OrdenTrabajo> listarCicloUtecoById(int id) throws Exception
		{ return OrdenTrabajoView.buscar("cu_id = " + id); }

	public static List<OrdenTrabajo> listarCicloUteco(CicloUteco ciclo,Boolean[] impresion, Boolean[] confeccion) throws Exception
		{
               String where = " ciclo_uteco_id = " + ciclo.getId();
                boolean filtroImpresion = impresion != null && impresion.length == 3 && !(impresion[0] && impresion[1]);
		boolean filtroConfeccion = confeccion != null && confeccion.length == 3 && !(confeccion[0] && confeccion[1]);
                if(filtroImpresion || filtroConfeccion)
			{
			if(filtroImpresion)
				{
				where += " AND (false";
				if(impresion[0]) where += " OR (estado_id = 1 AND cu_planificado = 0) ";
				if(impresion[1]) where += " OR (cu_planificado = 1 AND estado_id <> 2)";
				if(impresion[2]) where += " OR estado_id <> 1 ";
				where += ")";
				}

			if(filtroConfeccion)
				{
				where += " AND (false";
				if(confeccion[0]) where += " OR (estado_id <> 3 AND cn_planificado = 0) ";
				if(confeccion[1]) where += " OR (cn_planificado = 1 AND estado_id <> 3)  ";
				if(confeccion[2]) where += " OR estado_id = 3 ";
				where += ")";
				}

			}
                where += " ORDER BY ciclo_uteco_turno ASC";
		List<OrdenTrabajo> ordenes = OrdenTrabajoView.buscar(where);
		for(int i=0,n=ordenes.size(); i<n; i++) {ordenes.get(i).setCicloUteco(ciclo); }
		return ordenes;
		}

        public static List<OrdenTrabajo> listarCicloNewlong(CicloNewlong ciclo) throws Exception{
            return listarCicloNewlong(ciclo, null, null);
        }


        public static List<OrdenTrabajo> listarCicloNewlong(CicloNewlong ciclo,Boolean[] impresion, Boolean[] confeccion) throws Exception
		{
                String where = " ciclo_newlong_id = " + ciclo.getId();
                boolean filtroImpresion = impresion != null && impresion.length == 3 && !(impresion[0] && impresion[1]);
		boolean filtroConfeccion = confeccion != null && confeccion.length == 3 && !(confeccion[0] && confeccion[1]);
                if(filtroImpresion || filtroConfeccion)
			{
			if(filtroImpresion)
				{
				where += " AND (false";
				if(impresion[0]) where += " OR (estado_id = 1 AND cu_planificado = 0) ";
				if(impresion[1]) where += " OR (cu_planificado = 1 AND estado_id = 1) ";
				if(impresion[2]) where += " OR estado_id <> 1 ";
				where += ")";
				}

			if(filtroConfeccion)
				{
				where += " AND (false";
				if(confeccion[0]) where += " OR (estado_id <> 3 AND cn_planificado = 0)  ";
				if(confeccion[1]) where += " OR (cn_planificado = 1 AND  estado_id  <> 3) ";
				if(confeccion[2]) where += " OR estado_id = 3 ";
				where += ")";
				}

			}
                where += " ORDER BY ciclo_newlong_turno ASC";
		List<OrdenTrabajo> ordenes = OrdenTrabajoView.buscar(where);
		for(int i=0,n=ordenes.size(); i<n; i++) {ordenes.get(i).setCicloNewlong(ciclo); }
		return ordenes;
		}
	
	public static List<OrdenTrabajo> listarOrdenVenta(int ordenVentaId) throws Exception
		{ return (List) Entidad.buscar(OrdenTrabajo.class, NOMBRE_TABLA, "orden_venta_id = " + ordenVentaId); }
	
	public static List<OrdenTrabajo> buscar(int formatoId, int estadoId, int logotipoId, Date fechaEntrega1, Date fechaEntrega2, int newlongId, int utecoId) throws SQLException
		{
		Map<Integer, Boolean> estados = new HashMap();
		estados.put(estadoId, Boolean.TRUE);
		return OrdenTrabajo.buscar(formatoId, estados, logotipoId, fechaEntrega1, fechaEntrega2, newlongId, utecoId);
		}

	public static List<OrdenTrabajo> buscar(int formatoId, Map<Integer, Boolean> estados, int logotipoId, Date fechaEntrega1, Date fechaEntrega2, int newlongId, int utecoId) throws SQLException
		{ return buscar(formatoId, estados, logotipoId, fechaEntrega1, fechaEntrega2, newlongId, utecoId, 0); }
	
	public static List<OrdenTrabajo> buscar(int formatoId, Map<Integer, Boolean> estados, int logotipoId, Date fechaEntrega1, Date fechaEntrega2, int newlongId, int utecoId, int usuarioId) throws SQLException
		{ return buscar(formatoId, estados, logotipoId, fechaEntrega1, fechaEntrega2, newlongId, utecoId, usuarioId, 0); }

	public static List<OrdenTrabajo> buscar(int formatoId, Map<Integer, Boolean> estados, int logotipoId, Date fechaEntrega1, Date fechaEntrega2, int newlongId, int utecoId, int usuarioId, int paisId) throws SQLException
		{ return buscar(formatoId, estados, logotipoId, fechaEntrega1, fechaEntrega2, newlongId, utecoId, usuarioId, paisId, 0); }
	
	public static List<OrdenTrabajo> buscar(int formatoId, Map<Integer, Boolean> estados, int logotipoId, Date fechaEntrega1, Date fechaEntrega2, int newlongId, int utecoId, int usuarioId, int paisId, int lineaId) throws SQLException
		{
		String where = "TRUE";
		if(formatoId > 0) where += " AND formato_id = " + formatoId;
		if(estados != null)
			{
			where += " AND ( FALSE ";
			List<EstadoTrabajo> est = EstadoTrabajo.listar();
			for(int i=0; i<est.size(); i++)
				{
				if(estados.get(est.get(i).getId()) != null && estados.get(est.get(i).getId()) == true)
					{ where += " OR estado_id = " + est.get(i).getId(); }
				}
			where += " )";
			}
		if(fechaEntrega1 != null) where += " AND fecha_prometida >= " + MySQL.formatDateMin(fechaEntrega1);
		if(fechaEntrega2 != null) where += " AND fecha_prometida <= " + MySQL.formatDateMax(fechaEntrega2);
		if(logotipoId > 0) where += " AND ov_logotipo_id = " + logotipoId;
		if(newlongId > 0) where += " AND cn_newlong_id = " + newlongId;
		if(utecoId > 0) where += " AND cu_uteco_id = " + utecoId;
		if(usuarioId > 0) where += " AND ov_alta_usuario_id = " + usuarioId;
		if(paisId > 0) where += " AND ov_pais_id = " + paisId;
		if(lineaId > 0) where += " AND ov_linea_id = " + lineaId;

		return OrdenTrabajoView.buscar(where);
		}

	/**
	 * Verifica si la orden puede ser reprogramado (es decir, si se lo puede mover a otro ciclo.
	 *
	 * @return Devuelve 'true' si la orden puede ser reprogramada, 'false' en caso contrario.
	 */
	public boolean isReprogramable() throws SQLException
		{
		if(fechaPrometida != null && fechaPrometida.getTime() < new Date().getTime())
			{ return false; }

		CicloNewlong cicloN = getCicloNewlong();
		CicloUteco cicloU = getCicloUteco();
		
		return (cicloN == null || !cicloN.isBloqueado()) && (cicloU == null || !cicloU.isBloqueado());
		}

	public static Map<Integer, Float> getEstadisticaFormatos(Date fecha1, Date fecha2) throws SQLException
		{
		HashMap<Integer, Float> res = new HashMap();
		long total = 0;

		String query = "SELECT formato_id, SUM(cantidad) AS total FROM " + NOMBRE_TABLA + " WHERE true";
		if(fecha1 != null) query += " AND ciclo_newlong_fin >= "+MySQL.formatDateMin(fecha1);
		if(fecha2 != null) query += " AND ciclo_newlong_fin <= "+MySQL.formatDateMax(fecha2);
		query += " GROUP BY formato_id";

		ResultSet result = MySQL.executeQuery(query);
		while(result.next())
			{
			total += result.getLong("total");
			res.put(result.getInt("formato_id"), result.getFloat("total"));
			}
		result.getStatement().close();
		
		Iterator<Integer> iter = res.keySet().iterator();
		while(iter.hasNext())
			{
			int formatoId = iter.next();
			res.put(formatoId, res.get(formatoId)/total);
			}

		return res;
		}

	public static Map<Integer, Float> getDemandaDiariaFormatos(Date fecha1, Date fecha2) throws SQLException
		{
		HashMap<Integer, Float> res = new HashMap();
		int dias = Util.diferencia(fecha1, fecha2, "d") + 1;

		String query = "SELECT formato_id, SUM(cantidad) AS total FROM " + NOMBRE_TABLA + " WHERE true";
		if(fecha1 != null) query += " AND ciclo_newlong_fin >= "+MySQL.formatDateMin(fecha1);
		if(fecha2 != null) query += " AND ciclo_newlong_fin <= "+MySQL.formatDateMax(fecha2);
		query += " GROUP BY formato_id";

		ResultSet result = MySQL.executeQuery(query);
		while(result.next())
			{
			res.put(result.getInt("formato_id"),
					result.getFloat("total") / dias);
			}
		result.getStatement().close();
		
		return res;
		}

	/**
	 * Calcula las posibles fechas de entrega para una orden.
	 *
	 * Devuelve un objeto Map con la Newlong, la cantidad disponible,
	 * el numero de ciclo newlong, las fechas de entrega y de fin,
	 * el numero de ciclo uteco y si la orden requeriría autorización.
	 * (newlongId, cantidadDisponible, cicloNewlongId, cicloNewlongNumero, fechaHoraInicio, fechaHoraFin, fechaPrometida, cicloUtecoId).
	 *
	 * @return Devuelve un objeto Map con la Newlong, el número de ciclo, la cantidad disponible, las fechas de entrega y de fin, el numero de ciclo uteco y si requiere autorizacion (newlongId, cicloId, fechaInicio, fechaFin, cicloUtecoId, autorizar).
	 */
	public List<Map> calcularFechasPosibles(Long cantidadOrdenVentaFormato) throws SQLException, Exception
		{
		List<Map> res = new LinkedList();
		// Obtengo las fechas posibles para una orden de confeccion y verifico cuales de ellas pueden ser impresas.
                List<Map> ciclosNewlong = CicloNewlong.fechasPosibles(this.formatoId, this.cantidad);
		for(int o=0; o<ciclosNewlong.size(); o++)
			{
			Map cicloN = ciclosNewlong.get(o);
			Integer paisId = (Integer)cicloN.get("paisId");
                        Long cantidad = (Long) cicloN.get("cantidadDisponible");
//                        if(this.getOrdenVenta().getPaisId() == paisId && cantidad >= cantidadOrdenVentaFormato)
                        if(this.getOrdenVenta().getPaisId() == paisId && cantidad >0)
                            {
				this.setCicloNewlongId((Integer)cicloN.get("cicloNewlongId"));
					HashMap map = new HashMap();
					map.put("newlongId", cicloN.get("newlongId"));
					map.put("cantidadDisponible", cicloN.get("cantidadDisponible"));
					map.put("porcentajeDisponible", cicloN.get("porcentajeDisponible"));
					map.put("capacidad", cicloN.get("capacidad"));
					map.put("cicloNewlongId", cicloN.get("cicloNewlongId"));
					map.put("cicloNewlongNumero", cicloN.get("cicloNewlongNumero"));
					map.put("fechaHoraInicio", Util.format((Date)cicloN.get("fechaHoraInicio"), "dd/MM/yyyy HH:mm:ss"));
					map.put("fechaHoraFin", Util.format((Date)cicloN.get("fechaHoraFin"), "dd/MM/yyyy HH:mm:ss"));
					map.put("fechaPrometida", Util.format( new Date(((Date)cicloN.get("fechaHoraFin")).getTime() + Tiempos.getDiasDespacho(this.getOrdenVenta().getPaisId(), (Integer)cicloN.get("newlongId"), this.getFormato().getLineaId())*86400000), "dd/MM/yyyy"));
					//map.put("cicloUtecoId", cicloU.getId());
					res.add(map);
				}
			}

		return res;
		}

        /*La fecha prometida debe ser el dia en el q empieza la semana en la que se promete*/
        public List<Map> calcularFechasPosiblesParaVentas(Long cantidadOrdenVentaFormato) throws SQLException, Exception
		{
		List<Map> res = new LinkedList();
		// Obtengo las fechas posibles para una orden de confeccion y verifico cuales de ellas pueden ser impresas.
                List<Map> ciclosNewlong = CicloNewlong.fechasPosibles(this.formatoId, this.cantidad);
		for(int o=0; o<ciclosNewlong.size(); o++)
			{
			Map cicloN = ciclosNewlong.get(o);
			Integer paisId = (Integer)cicloN.get("paisId");
                        Long cantidad = (Long) cicloN.get("cantidadDisponible");
//                        if(this.getOrdenVenta().getPaisId() == paisId && cantidad >= cantidadOrdenVentaFormato)
                        if(this.getOrdenVenta().getPaisId() == paisId && cantidad >0)
                            {
				this.setCicloNewlongId((Integer)cicloN.get("cicloNewlongId"));
					HashMap map = new HashMap();
					map.put("newlongId", cicloN.get("newlongId"));
					map.put("cantidadDisponible", cicloN.get("cantidadDisponible"));
					map.put("porcentajeDisponible", cicloN.get("porcentajeDisponible"));
					map.put("capacidad", cicloN.get("capacidad"));
					map.put("cicloNewlongId", cicloN.get("cicloNewlongId"));
					map.put("cicloNewlongNumero", cicloN.get("cicloNewlongNumero"));
					map.put("fechaHoraInicio", Util.format((Date)cicloN.get("fechaHoraInicio"), "dd/MM/yyyy HH:mm:ss"));
					map.put("fechaHoraFin", Util.format((Date)cicloN.get("fechaHoraFin"), "dd/MM/yyyy HH:mm:ss"));
					
                                        Date fechaPrometidaExacta = new Date(((Date)cicloN.get("fechaHoraFin")).getTime() + Tiempos.getDiasDespacho(this.getOrdenVenta().getPaisId(), (Integer)cicloN.get("newlongId"), this.getFormato().getLineaId())*86400000);
                                        Date inicioDeSemana = Util.obtenerInicioDeSemana(fechaPrometidaExacta);
                                        map.put("fechaPrometida", Util.format( inicioDeSemana, "dd/MM/yyyy"));
					res.add(map);
				}
			}

		return res;
		}

    public List<Map> calcularFechasPosiblesSoloReprogramar() throws SQLException
		{
		List<Map> res = new LinkedList();

		// Obtengo las fechas posibles para una orden de confeccion y verifico cuales de ellas pueden ser impresas.
                List<Map> ciclosNewlong = CicloNewlong.fechasPosiblesSoloReprogramar(this.formatoId, this.cantidad,this.getFechaPrometida(), false);
		for(int o=0; o<ciclosNewlong.size(); o++)
			{
			Map cicloN = ciclosNewlong.get(o);
			Integer paisId = (Integer)cicloN.get("paisId");
//                        Newlong newlong = Newlong.getNewLongById((Integer)cicloN.get("newlongId"));

			// Verifico que, si el cliente es de Argentina, la confeccionadora tambien lo sea.
//			if(this.getOrdenVenta().getPaisId() != Pais.ARGENTINA || this.getOrdenVenta().getPaisId() == paisId)
                        if(this.getOrdenVenta().getPaisId() == paisId)

                            {
				this.setCicloNewlongId((Integer)cicloN.get("newlongId"));
         			// Busco una fecha de impresion en la que:
				// - La diferencia entre la fecha actual y la fecha de impresion sea mayor a los dias dados por 'Tiempos.diasEspera'.
				// - El tiempo entre que la orden es impresa y entre que es confeccionado sea mayor o igual a los dias dados por 'Tiempos.diasDeposito'.
                                CicloUteco cicloU = CicloUteco.getDisponible((Date)cicloN.get("fechaHoraInicio"), this);
				if(cicloU != null && cicloU.getId() != 0 )
					{
                                        HashMap map = new HashMap();
					map.put("newlongId", cicloN.get("newlongId"));
					map.put("cantidadDisponible", cicloN.get("cantidadDisponible"));
					map.put("porcentajeDisponible", cicloN.get("porcentajeDisponible"));
					map.put("capacidad", cicloN.get("capacidad"));
					map.put("cicloNewlongId", cicloN.get("cicloNewlongId"));
					map.put("cicloNewlongNumero", cicloN.get("cicloNewlongNumero"));
					map.put("fechaHoraInicio", Util.format((Date)cicloN.get("fechaHoraInicio"), "dd/MM/yyyy HH:mm:ss"));
					map.put("fechaHoraFin", Util.format((Date)cicloN.get("fechaHoraFin"), "dd/MM/yyyy HH:mm:ss"));
					map.put("fechaPrometida", Util.format( new Date(((Date)cicloN.get("fechaHoraFin")).getTime() + Tiempos.getDiasDespacho(this.getOrdenVenta().getPaisId(), (Integer)cicloN.get("newlongId"), this.getFormato().getLineaId())*86400000), "dd/MM/yyyy"));
					map.put("cicloUtecoId", cicloU.getId());
					res.add(map);
					}
				}
			}

		return res;
		}

    public static long calcularMetros(long cantidad, int formatoId, boolean interior) throws SQLException
		{
		Formato formato = new Formato(formatoId);
		return (long)(formato.getDesarrollo() * cantidad * (interior? 2 : 1) / 100);
		}
	
	public void calcularMetros() throws SQLException
		{
		OrdenVenta ov = this.getOrdenVenta();
		this.metros = calcularMetros(this.cantidad, this.formatoId, ov.isInterior());
		}
	
	
	public static OrdenTrabajo buscar(String workOrder) throws SQLException
		{
		OrdenTrabajo ov = new OrdenTrabajo();
		
		ResultSet result = MySQL.executeQuery("SELECT * FROM " + NOMBRE_TABLA + " WHERE identificador = " + MySQL.format(workOrder));
		if(result.next()) { ov.leer(result); }
		result.getStatement().close();
		
		return ov;
		}
        public static OrdenTrabajo buscarByCicloUteco(CicloUteco cicloUteco) throws SQLException
		{
		OrdenTrabajo ov = new OrdenTrabajo();

		ResultSet result = MySQL.executeQuery("SELECT * FROM " + NOMBRE_TABLA + " WHERE ciclo_uteco_id = " + cicloUteco.getId());
		if(result.next()) { ov.leer(result); }
		result.getStatement().close();

		return ov;
		}
        public static OrdenTrabajo buscarById(String workOrder) throws SQLException
		{
		OrdenTrabajo ov = new OrdenTrabajo();

		ResultSet result = MySQL.executeQuery("SELECT * FROM " + NOMBRE_TABLA + " WHERE id = " + MySQL.format(workOrder));
		if(result.next()) { ov.leer(result); }
		result.getStatement().close();

		return ov;
		}

          public List<Map> calcularFechasPosiblesSoloImpresion() throws SQLException
		{
		List<Map> res = new LinkedList();

		List<Map> ciclosNewlong = CicloUteco.fechasPosibles(this);
                for(int o=0; o<ciclosNewlong.size(); o++)
			{
			Map cicloN = ciclosNewlong.get(o);
                        this.setCicloUtecoId((Integer)cicloN.get("newlongId"));
			HashMap map = new HashMap();
			map.put("newlongId", cicloN.get("newlongId"));
			map.put("cantidadDisponible", cicloN.get("cantidadDisponible"));
			map.put("porcentajeDisponible", cicloN.get("porcentajeDisponible"));
			map.put("capacidad", cicloN.get("capacidad"));
			map.put("cicloNewlongNumero", 0);
			map.put("fechaHoraInicio", Util.format((Date)cicloN.get("fechaHoraInicio"), "dd/MM/yyyy HH:mm:ss"));
			map.put("fechaHoraFin", Util.format((Date)cicloN.get("fechaHoraFin"), "dd/MM/yyyy HH:mm:ss"));
			map.put("fechaPrometida", Util.format( new Date(((Date)cicloN.get("fechaHoraFin")).getTime() + Tiempos.getDiasDespacho(this.getOrdenVenta().getPaisId(), (Integer)cicloN.get("newlongId"), this.getFormato().getLineaId())*86400000), "dd/MM/yyyy"));
			map.put("cicloUtecoId", cicloN.get("cicloUtecoId"));
                        map.put("cicloNewlongId", 0);

                        res.add(map);
			}

		return res;
		}


         public static List<OrdenTrabajo> listarCicloUteco(CicloUteco ciclo,Boolean[] confeccion) throws Exception
		{
               String where = " ciclo_uteco_id = " + ciclo.getId();
		boolean filtroConfeccion = confeccion != null && confeccion.length == 3 && !(confeccion[0] && confeccion[1]);
                if(filtroConfeccion)
			{
			if(filtroConfeccion)
				{
				where += " AND (false";
				if(confeccion[0]) where += " OR (estado_id <> 3 AND cn_planificado = 0) ";
				if(confeccion[1]) where += " OR (cn_planificado = 1 AND estado_id <> 3)  ";
				if(confeccion[2]) where += " OR estado_id = 3 ";
				where += ")";
				}

			}
                where += " ORDER BY cu_fecha_hora_inicio ASC";
		List<OrdenTrabajo> ordenes = OrdenTrabajoView.buscar(where);
		for(int i=0,n=ordenes.size(); i<n; i++) {ordenes.get(i).setCicloUteco(ciclo); }
		return ordenes;
	}

   public static List<OrdenTrabajo> listarCicloUtecoByNumero(CicloUteco ciclo,Boolean[] confeccion) throws Exception
		{
               String where = " cu_numero = " + ciclo.getNumero();
		boolean filtroConfeccion = confeccion != null && confeccion.length == 3 && !(confeccion[0] && confeccion[1]);
                if(filtroConfeccion)
			{
			if(filtroConfeccion)
				{
				where += " AND (false";
				if(confeccion[0]) where += " OR (estado_id <> 3 AND cn_planificado = 0) ";
				if(confeccion[1]) where += " OR (cn_planificado = 1 AND estado_id <> 3)  ";
				if(confeccion[2]) where += " OR estado_id = 3 ";
				where += ") ";
				}

			}
                where += " ORDER BY cu_fecha_hora_inicio ASC";
		List<OrdenTrabajo> ordenes = OrdenTrabajoView.buscar(where);
		for(int i=0,n=ordenes.size(); i<n; i++) {ordenes.get(i).setCicloUteco(ciclo); }
		return ordenes;
	}

  public static List<OrdenTrabajo> getOrdenesTrabajoParientes(OrdenVenta ov, OrdenTrabajo ot){
        String where = " 1 =1 ";
        where += " and id != " + ot.getId() + " and orden_venta_id = " + ov.getId();
        try {
            return OrdenTrabajoView.buscar(where);
        } catch (SQLException ex) {
            Logger.getLogger(OrdenTrabajo.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    public int getSemanaNewlong() throws SQLException{
        double dias = this.getCicloNewlong().getFechaHoraInicio().getTime() +  + 86400000*6.5;
        if (this.getCicloNewlongInicio().getTime() >= this.getCicloNewlong().getFechaHoraInicio().getTime() &&
             this.getCicloNewlongInicio().getTime() < dias   ){
            return 1;
        }else{
            return 2;
        }
    }

    public int getSemanaNewlong(Date fecha) throws SQLException{
        long dias = fecha.getTime() +  + 86400000*7;
        if (this.getCicloNewlongInicio() != null && this.getCicloNewlongInicio().getTime() >= fecha.getTime() &&
             this.getCicloNewlongInicio().getTime() < dias   ){
            return 1;
        }else{
            return 2;
        }
    }

    public static String getLastByLineaId(int idLinea) throws SQLException{
            String query = "select  ot.identificador from ordenes_trabajo ot inner join ordenes_venta ov on (ov.id = ot.orden_venta_id)";
            query +=  " where ov.linea_id = " + idLinea + " AND ot.identificador REGEXP '^[0-9]+$' ORDER BY ot.identificador desc LIMIT 1 ";
            ResultSet result = MySQL.executeQuery(query);
            String idWO = "";
            while(result.next())
				{
                                  idWO = result.getString(1);
				}
            String salida = "";
            try{
                int id = Integer.parseInt(idWO) + 1;
                salida = String.valueOf(id);
          }catch(Exception e){}
            
           return salida;
        }

    public static List<OrdenTrabajo> getOrdenesSinFechaPrometida() throws SQLException{
           LinkedList lista = new LinkedList();

            String query = "SELECT * FROM " + NOMBRE_TABLA + " where fecha_prometida is null " ;

            ResultSet result = null;
        try {
            result = MySQL.executeQuery(query);
            } catch (SQLException ex) {
                Logger.getLogger(CicloNewlong.class.getName()).log(Level.SEVERE, null, ex);
            }

			while(result.next())
				{
                                OrdenTrabajo entidad = null;
                                try {
                                    entidad = (OrdenTrabajo) OrdenTrabajo.class.newInstance();
                                    }catch (InstantiationException ex) {
                                    Logger.getLogger(CicloNewlong.class.getName()).log(Level.SEVERE, null, ex);
                                    } catch (IllegalAccessException ex) {
                                    Logger.getLogger(CicloNewlong.class.getName()).log(Level.SEVERE, null, ex);
                                   }
                                    entidad.leer(result);
                                   lista.add(entidad);
				}
                            result.getStatement().close();

            return lista;
        }

       public static CicloUteco getCicloUtecoDisponible(OrdenTrabajo orden, Date fechaConfeccion) throws SQLException
		{
		CicloUteco cu = new CicloUteco();

		String query = "SELECT * FROM ciclos_uteco_view WHERE ";
		query += "fecha_hora_fin <= " + MySQL.format(fechaConfeccion) + " AND ";
		query += "metros_disponibles >= " + orden.getMetros() + " ";
		query += "ORDER BY numero DESC, metros_disponibles DESC, fecha_hora_fin DESC LIMIT 1";

		ResultSet result = MySQL.executeQuery(query);
		if(result.next()) { cu.leer(result); }
		result.close();

		return cu;
		}

        public static List<OrdenTrabajo> buscarDemoradas(int formatoId, int logotipoId, int usuarioId, int paisId, int lineaId) throws SQLException, InstantiationException, IllegalAccessException
		{
            LinkedList lista = new LinkedList();
            String query = "SELECT * FROM ordenes_trabajo ot inner join ordenes_venta ov on (ot.orden_venta_id = ov.id) WHERE ";
		query += "ot.estado_id = 4 ";
                if(logotipoId > 0) query += " AND ov.logotipo_id = " + logotipoId;
                if(usuarioId > 0) query += " AND ov.alta_usuario_id = " + usuarioId;
                if(paisId > 0) query += " AND ov.pais_id = " + paisId;
                if(lineaId > 0) query += " AND ov_linea_id = " + lineaId;

                ResultSet result = MySQL.executeQuery(query);
		while(result.next()) {
                    OrdenTrabajo entidad = (OrdenTrabajo) OrdenTrabajo.class.newInstance();
                    entidad.leer(result);
                    lista.add(entidad);
                }
	 	   result.close();

		return lista;
		}

    
}
